/**
 * 
 */
package com.search;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;

import org.joy.analyzer.html.Anchor;
import org.joy.analyzer.html.HTMLDocument;
import org.joy.analyzer.html.Utility;

import com.Constant.Contants;
import com.crawl.MetaSearch;
import com.link.LinkDB;
import com.link.Queue;
import com.parser.PageAnalysis;

/**
 * @author LvSaiHui {gurnfe@163.com}
 * @version 1.0 <br>
 *          Copyright (C), 2007-2008, ZJUT <br>
 *          This program is protected by copyright laws. <br>
 *          Program Name: MultiThreadSAGA.java <br>
 *          Date: 2009-3-3 <br>
 *          Description:
 */
public class MultiThreadSAGA implements Runnable {
	public static Map nextGenerationUrls = new HashMap<String, Double>();
	private   float crossProbability = 0.2f;

	public  void run() {

		while (LinkDB.getVisitedUrlNum() < Contants.visitedUrlCount) {
			if (!LinkDB.getUnVisitedUrl().empty()) {

				Queue<String> unVisitedUrlQueue = LinkDB.getUnVisitedUrl();
				String url = unVisitedUrlQueue.deQueue();
				double webPageSimilarity = 0.0;
				HTMLDocument doc = null;
				try {
					doc = HTMLDocument.createHTMLDocument(url, Utility
							.getWebContent(url));
					webPageSimilarity = Similarity.scoreOnWebPageText(url, doc);
				} catch (Exception e) {
					e.printStackTrace();
				}
				
				if (webPageSimilarity > Contants.selectionProbability) {
					// save doc to local disk expected
					try {
						PageAnalysis.saveSourceCodeToLocalDisk(url);
					} catch (Exception e) {
						e.printStackTrace();
					}
					for (Anchor a : doc.getAnchors()) {
						if (a != null && a.getText().trim().length() > 0) {
							double pageRankScore = Similarity.scoreOnPageRank(a
									.getURL());
							double urlTextScore = Similarity
									.scoreBasedOnUrlText(a.getText());
							double ecpectedLinkValue = webPageSimilarity
									+ pageRankScore + urlTextScore;
							System.out.println("The ecpected link value :"
									+ ecpectedLinkValue + "="
									+ "parentPageScore:" + webPageSimilarity
									+ "pageRankScore:" + pageRankScore
									+ "urlTextScore:" + urlTextScore);
							synchronized (nextGenerationUrls) {
								if (!nextGenerationUrls.containsKey(a.getURL())) {
									nextGenerationUrls.put(a.getURL(),
											ecpectedLinkValue);
								}
							}
						}

					}
				}

			} else {
				// 暂停所有线程，直到第2代url生成。
				synchronized(this){
					try {
						this.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
				}
				synchronized (nextGenerationUrls){
					if (!nextGenerationUrls.isEmpty()) {
						System.out
								.println("The original size of nextGenerationUrls before cross operation : "
										+ nextGenerationUrls.size());
						int pushTonNextGenNum = Float
								.floatToRawIntBits(nextGenerationUrls.size()
										* crossProbability);
						for (int k = 0; k < pushTonNextGenNum; k++) {
							Iterator it = nextGenerationUrls.entrySet().iterator();
							String highScoreKey = null;
							double highScore = 0;
							while (it.hasNext()) {
								Map.Entry entry = (Map.Entry) it.next();
								if ((Double) entry.getValue() > highScore) {
									highScoreKey = (String) entry.getKey();
									highScore = (Double) entry.getValue();
								}

							}
							if (highScoreKey != null) {
								LinkDB.getUnVisitedUrl().enQueue(highScoreKey);
								nextGenerationUrls.remove(highScoreKey);
							}

						}

					}
					Random rd = new Random();
					if(rd.nextInt(100)<5){
						String mutationUrl=null;
						try {
							mutationUrl = MetaSearch.getMutationUrlBasedCorpusSearch();
						} catch (UnsupportedEncodingException e) {
							e.printStackTrace();
						}
						if(mutationUrl!=null){
						LinkDB.getUnVisitedUrl().enQueue(mutationUrl);}
					}
					if (!nextGenerationUrls.isEmpty()){
						//重启动所有线程程
						this.notifyAll();
						
					}
					else{
						break;
					}
					
				}
				
			}

		}

	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		 MultiThreadSAGA mtsaga= new MultiThreadSAGA();
		 Thread[] threads=new Thread[10];

		for (int i = 0; i < threads.length; i++) {
			threads[i]=new Thread(mtsaga);
			threads[i].start();
		}
	}

}
